/**
 * fshows.com
 * Copyright (C) 2013-2019 All Rights Reserved.
 */
package com.example.proxydemo.mycglib;

import com.example.proxydemo.mycglib.model.SourceProxyModel;
import com.example.proxydemo.pay.H5Pay;
import com.example.proxydemo.pay.MyZeroRateInterceptor;
import com.example.proxydemo.pay.impl.H5PayImpl;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 代理工厂
 *
 * @author Liluqing
 * @version ProxyFactory.java, v 0.1 2019-08-08 13:52
 */
public class ProxyFactory {

    /**
     * 创建代理对象
     *
     * @param target 被代理对象
     * @param interceptor 自定义拦截器
     * @return
     * @throws ClassNotFoundException
     */
    public static Object newInstance(Object target, MyMethodInterceptor interceptor) {
        // 1. 根据模版生成代理类源码,使用技术：模版引擎，反射，IO,
        SourceProxyModel sourceProxyModel = GenerateSourceCodeUtil.generateCodeFile(target.getClass());
        // 2. 编译代理类,技术点：java运行时编译,
        JavaCompilerUtil.compile(sourceProxyModel.getSourceFile().getAbsolutePath());
        // 3. 加载代理类,技术点: 自定义类加载器
        // Class proxyClass = Class.forName(sourceProxyModel.getFullClassName());
        MyClassLoader classLoader = new MyClassLoader(sourceProxyModel.getSourceFile().getParent());
        Class proxyClass = null;
        try {
            proxyClass = classLoader.findClass(sourceProxyModel.getFullClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 4. 创建代理对象并返回，反射创建
        return doNewProxyInstance(proxyClass, target, interceptor);
    }


    /**
     * 创建代理对象
     *
     * @param proxyClass
     * @param target
     * @param interceptor
     * @return
     */
    private static Object doNewProxyInstance(Class proxyClass, Object target, MyMethodInterceptor interceptor) {
        try {
            // 获取构造器
            Constructor<?> constructor = proxyClass.getConstructor(Object.class, MyMethodInterceptor.class);
            return constructor.newInstance(target, interceptor);
        } catch (NoSuchMethodException e) {
            System.out.println("没有找到对应的构造器！");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

}